import java.awt.Graphics;
import java.awt.Point;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.image.BufferStrategy;
import javax.swing.JFrame;

public class Game implements Runnable {
	JFrame frame;
	Grid grid;
	StatPanel statPanel;
	HeartContainer hearts;
	MyButton menuButton, titleButton, respawnButton;

	boolean running, alive, restart;
	int level, points, pairs;

	public Game() {
		createFrame();
		startGame();
	}

	public void createFrame() {
		frame = new JFrame();
		frame.setSize(800, 640);
		frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
		frame.setResizable(false);
		frame.setUndecorated(true);
		frame.addMouseListener(new MouseListen());
		frame.addKeyListener(new KeyListen());
		frame.setLocationRelativeTo(null);
		frame.setVisible(true);
		frame.setIgnoreRepaint(true);
		frame.createBufferStrategy(2);
	}

	public void run() {
		running = true;
		restart = false;
		while (running) {
			update();
			checkDead();
			draw();

			try {
				Thread.sleep(20);
			} catch (InterruptedException e) {
			}
		}

		frame.dispose();
		if (restart) {
			new Game().run();
		} else {
			new Menu().run();
		}
	}

	public void startGame() {
		level = 0;
		points = 0;
		pairs = 0;
		alive = true;

		menuButton = new MyButton(549, 567,
				ImageLoader.images.get("menuButton"));

		statPanel = new StatPanel(level, points, pairs);
		statPanel.level = 1;

		hearts = new HeartContainer(10);

		nextLevel();
		run();

	}

	public void nextLevel() {
		level++;
		statPanel.level = level;
		statPanel.pairs = 0;
		hearts.health = 10;

		switch (level) {
		case 1:
			grid = new Grid(4, ImageLoader.images.get("background1"));
			break;
		case 2:
			grid = new Grid(5, ImageLoader.images.get("background2"));
			break;
		case 3:
			grid = new Grid(6, ImageLoader.images.get("background3"));
			break;
		case 4:
			grid = new Grid(8, ImageLoader.images.get("background4"));
			break;
		case 5:
			grid = new Grid(10, ImageLoader.images.get("background5"));
			break;
		case 6:
			grid = new Grid(12, ImageLoader.images.get("background6"));
			break;
		case 7:
			grid = new Grid(14, ImageLoader.images.get("background7"));
			break;
		case 8:
			grid = new Grid(16, ImageLoader.images.get("background8"));
			break;
		case 9:
			grid = new Grid(18, ImageLoader.images.get("background9"));
			break;
		case 10:
			grid = new Grid(18, ImageLoader.images.get("background10"));
			break;
		}
	}

	public boolean checkFinish() {
		Card[][] cards = grid.cards;
		for (int y = 0; y < cards.length; y++) {
			for (int x = 0; x < cards[0].length; x++) {
				Card temp = cards[x][y];

				if (temp.currentImage == temp.back) {
					return false;
				}
			}
		}

		return true;
	}

	public void checkDead() {
		if (hearts.health == 0) {
			respawnButton = new MyButton(31, 387,
					ImageLoader.images.get("respawnButton"));
			titleButton = new MyButton(31, 478,
					ImageLoader.images.get("titleMenuButton"));
			alive = false;
		}
	}

	public void update() {
		boolean levelFinished = checkFinish();

		if (levelFinished) {
			nextLevel();
		}
	}

	public void draw() {
		BufferStrategy strategy = frame.getBufferStrategy();
		Graphics g = strategy.getDrawGraphics();

		if (alive) {
			grid.draw(g);
			g.drawImage(ImageLoader.images.get("title"), 116, 10, null);
			statPanel.draw(g);
			hearts.draw(g);
			menuButton.draw(g);
		} else {
			g.drawImage(ImageLoader.images.get("gameOver"), 0, 0, null);
			respawnButton.draw(g);
			titleButton.draw(g);
		}
		g.dispose();

		if (!strategy.contentsLost()) {
			strategy.show();
		}
	}

	class MouseListen extends MouseAdapter {
		Card[] pair = new Card[2];
		int cardCounter = 0;
		int heartCounter =0;

		public void mousePressed(MouseEvent e) {
			Point p = new Point(e.getX(), e.getY());
			if (alive) {
				if (menuButton.contains(p)) {
					running = false;
				}

				Card[][] cards = grid.cards;
				for (int y = 0; y < cards.length; y++) {
					for (int x = 0; x < cards[0].length; x++) {
						Card temp = cards[x][y];

						if (temp.contains(p) && temp.currentImage == temp.back) {
							pair[cardCounter++] = temp;
							temp.flip();

						}

						if (cardCounter == 2 && pair[0].front != pair[1].front) {
							try {
								Thread.sleep(500);
							} catch (InterruptedException ex) {
							}

							pair[0].flip();
							pair[1].flip();
							if (heartCounter < 5) {
								heartCounter++;
							} else {
								heartCounter = 0;
							}
							
							if (hearts.health > 0 && heartCounter == 5) {
								hearts.health--;
							}

						} else if (cardCounter == 2
								&& pair[0].front == pair[1].front) {

							if (statPanel.points < 9) {
								statPanel.points++;
							} else if (statPanel.points == 9) {
								statPanel.points = 0;
								if (hearts.health < 10) {
									hearts.health++;
								}
							}

							statPanel.pairs++;
						}

						if (cardCounter >= pair.length) {
							cardCounter = 0;
						}
					}
				}
			} else {
				if (respawnButton.contains(p)) {
					restart = true;
					running = false;
				} else if (titleButton.contains(p)) {
					running = false;
				}
			}
		}
	}

	class KeyListen extends KeyAdapter {
		public void keyPressed(KeyEvent e) {
			if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
				System.exit(0);
			}
		}
	}
}
